package com.aabte.permissionframeworklearn.permission.service;

import com.aabte.permissionframeworklearn.permission.beans.LogType;
import com.aabte.permissionframeworklearn.permission.beans.PageQuery;
import com.aabte.permissionframeworklearn.permission.beans.PageResult;
import com.aabte.permissionframeworklearn.permission.common.RequestHolder;
import com.aabte.permissionframeworklearn.permission.dto.SearchLogDto;
import com.aabte.permissionframeworklearn.permission.exception.ParamException;
import com.aabte.permissionframeworklearn.permission.mapper.*;
import com.aabte.permissionframeworklearn.permission.model.*;
import com.aabte.permissionframeworklearn.permission.param.SearchLogParam;
import com.aabte.permissionframeworklearn.permission.util.BeanValidator;
import com.aabte.permissionframeworklearn.permission.util.IpUtil;
import com.aabte.permissionframeworklearn.permission.util.JsonMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author Daniel
 */
@Service
public class SysLogService {
    @Autowired
    private SysLogMapper sysLogMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysAclModuleMapper sysAclModuleMapper;
    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysRoleUserService sysRoleUserService;

    @Autowired
    private SysRoleAclService sysRoleAclService;

    public SysLogWithBLOBs recover(Long id) {
        SysLogWithBLOBs sygLog = sysLogMapper.selectByPrimaryKey(id);
        Preconditions.checkNotNull(sygLog, "待还原的记录不存在！");

        switch (sygLog.getType()) {
            case LogType.TYPE_DEPT:
                SysDept beforeDept = sysDeptMapper.selectByPrimaryKey(sygLog.getTargetId());
                Preconditions.checkNotNull(beforeDept, "待还原的部门已经不存在！");
                if (StringUtils.isBlank(sygLog.getOldValue()) || StringUtils.isBlank(sygLog.getNewValue())) {
                    throw new ParamException("新增和删除操作不支持还原！");
                }
                SysDept afterDept = JsonMapper.string2Obj(sygLog.getOldValue(), new TypeReference<SysDept>() {
                });
                afterDept.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterDept.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
                afterDept.setOperateTime(new Date());
                sysDeptMapper.updateByPrimaryKeySelective(afterDept);
                saveDeptLog(beforeDept, afterDept);
                break;
            case LogType.TYPE_USER:
                SysUser beforeUser = sysUserMapper.selectByPrimaryKey(sygLog.getTargetId());
                Preconditions.checkNotNull(beforeUser, "待还原的用户已经不存在！");
                if (StringUtils.isBlank(sygLog.getOldValue()) || StringUtils.isBlank(sygLog.getNewValue())) {
                    throw new ParamException("新增和删除操作不支持还原！");
                }
                SysUser afterUser = JsonMapper.string2Obj(sygLog.getOldValue(), new TypeReference<SysUser>() {
                });
                afterUser.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterUser.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
                afterUser.setOperateTime(new Date());
                sysUserMapper.updateByPrimaryKeySelective(afterUser);
                saveUserLog(beforeUser, afterUser);
                break;
            case LogType.TYPE_ACL_MODULE:
                SysAclModule beforeAclModule = sysAclModuleMapper.selectByPrimaryKey(sygLog.getTargetId());
                Preconditions.checkNotNull(beforeAclModule, "待还原的权限模块已经不存在！");
                if (StringUtils.isBlank(sygLog.getOldValue()) || StringUtils.isBlank(sygLog.getNewValue())) {
                    throw new ParamException("新增和删除操作不支持还原！");
                }
                SysAclModule afterAclModule = JsonMapper.string2Obj(sygLog.getOldValue(), new TypeReference<SysAclModule>() {
                });
                afterAclModule.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterAclModule.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
                afterAclModule.setOperateTime(new Date());
                sysAclModuleMapper.updateByPrimaryKeySelective(afterAclModule);
                saveAclModuleLog(beforeAclModule, afterAclModule);
                break;
            case LogType.TYPE_ACL:
                SysAcl beforeAcl = sysAclMapper.selectByPrimaryKey(sygLog.getTargetId());
                Preconditions.checkNotNull(beforeAcl, "待还原的权限点已经不存在！");
                if (StringUtils.isBlank(sygLog.getOldValue()) || StringUtils.isBlank(sygLog.getNewValue())) {
                    throw new ParamException("新增和删除操作不支持还原！");
                }
                SysAcl afterAcl = JsonMapper.string2Obj(sygLog.getOldValue(), new TypeReference<SysAcl>() {
                });
                afterAcl.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterAcl.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
                afterAcl.setOperateTime(new Date());
                sysAclMapper.updateByPrimaryKeySelective(afterAcl);
                saveAclLog(beforeAcl, afterAcl);
                break;
            case LogType.TYPE_ROLE:
                SysRole beforeRole = sysRoleMapper.selectByPrimaryKey(sygLog.getTargetId());
                Preconditions.checkNotNull(beforeRole, "待还原的角色已经不存在！");
                if (StringUtils.isBlank(sygLog.getOldValue()) || StringUtils.isBlank(sygLog.getNewValue())) {
                    throw new ParamException("新增和删除操作不支持还原！");
                }
                SysRole afterRole = JsonMapper.string2Obj(sygLog.getOldValue(), new TypeReference<SysRole>() {
                });
                afterRole.setOperator(RequestHolder.getCurrentUser().getUsername());
                afterRole.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
                afterRole.setOperateTime(new Date());
                sysRoleMapper.updateByPrimaryKeySelective(afterRole);
                saveRoleLog(beforeRole, afterRole);
                break;
            case LogType.TYPE_ROLE_ACL:
                SysRole aclRole = sysRoleMapper.selectByPrimaryKey(sygLog.getTargetId());
                Preconditions.checkNotNull(aclRole, "角色已经不存在！");
                List<Long> oldAclId = JsonMapper.string2Obj(sygLog.getOldValue(), new TypeReference<List<Long>>() {
                });
                sysRoleAclService.changeAcl(sygLog.getTargetId(), oldAclId);
                break;
            case LogType.TYPE_ROLE_USER:
                SysRole userRole = sysRoleMapper.selectByPrimaryKey(sygLog.getTargetId());
                Preconditions.checkNotNull(userRole, "角色已经不存在！");

                List<Long> oldUserId = JsonMapper.string2Obj(sygLog.getOldValue(), new TypeReference<List<Long>>() {
                });
                sysRoleUserService.changeUser(sygLog.getTargetId(), oldUserId);
                break;
            default:
                break;
        }

        sygLog.setStatus(1);
        sysLogMapper.updateByPrimaryKeySelective(sygLog);
        return sygLog;
    }

    public PageResult<SysLogWithBLOBs> searchPageList(SearchLogParam param, PageQuery page) {
        BeanValidator.check(page);

        SearchLogDto.SearchLogDtoBuilder builder = SearchLogDto.builder()
                .type(param.getType());

        if (StringUtils.isNotBlank(param.getBeforeSeg())) {
            builder.beforeSeg("%" + param.getBeforeSeg() + "%");
        }
        if (StringUtils.isNotBlank(param.getAfterSeg())) {
            builder.afterSeg("%" + param.getAfterSeg() + "%");
        }

        if (StringUtils.isNotBlank(param.getOperator())) {
            builder.operator("%" + param.getOperator() + "%");
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            if (StringUtils.isNotBlank(param.getFromTime())) {
                builder.fromTime(dateFormat.parse(param.getFromTime()));
            }
            if (StringUtils.isNotBlank(param.getToTime())) {
                builder.toTime(dateFormat.parse(param.getToTime()));
            }
        } catch (Exception e) {
            throw new ParamException("日期格式不正确，正确格式为：yyyy-MM-dd HH:mm:ss");
        }

        SearchLogDto searchLogDto = builder.build();
        long total = sysLogMapper.countBySearchDto(searchLogDto);
        if (total <= 0) {
            return PageResult.<SysLogWithBLOBs>builder().total(0L).data(Lists.newArrayList()).build();
        } else {
            List<SysLogWithBLOBs> sysLogs = sysLogMapper.getPageListBySearchDto(page, searchLogDto);
            return PageResult.<SysLogWithBLOBs>builder().total(total).data(sysLogs).build();
        }
    }

    public void saveDeptLog(SysDept before, SysDept after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_DEPT);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2String(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2String(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setStatus(1);
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveUserLog(SysUser before, SysUser after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_USER);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2String(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2String(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setStatus(1);
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveAclModuleLog(SysAclModule before, SysAclModule after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_ACL_MODULE);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2String(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2String(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setStatus(1);
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveAclLog(SysAcl before, SysAcl after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_ACL);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2String(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2String(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setStatus(1);
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveRoleLog(SysRole before, SysRole after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_ROLE);
        sysLogWithBLOBs.setTargetId(after == null ? before.getId() : after.getId());
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2String(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2String(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setStatus(1);
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveRoleUserLog(Long roleId, List<Long> before, List<Long> after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_ROLE_USER);
        sysLogWithBLOBs.setTargetId(roleId);
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2String(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2String(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setStatus(1);
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }

    public void saveRoleAclLog(Long roleId, List<Long> before, List<Long> after) {
        SysLogWithBLOBs sysLogWithBLOBs = new SysLogWithBLOBs();
        sysLogWithBLOBs.setType(LogType.TYPE_ROLE_ACL);
        sysLogWithBLOBs.setTargetId(roleId);
        sysLogWithBLOBs.setOldValue(before == null ? "" : JsonMapper.obj2String(before));
        sysLogWithBLOBs.setNewValue(after == null ? "" : JsonMapper.obj2String(after));
        sysLogWithBLOBs.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysLogWithBLOBs.setOperateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()));
        sysLogWithBLOBs.setOperateTime(new Date());
        sysLogWithBLOBs.setStatus(1);
        sysLogMapper.insertSelective(sysLogWithBLOBs);
    }


}
